import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;

/**
 * 
 */

/**
 * @author ES
 *
 */
public class HeuristicSearch {

	private PriorityQueue<State> openListQ; //Open list
	private LinkedList<State> closedList = new LinkedList<State>();
	
	
	/**
	 * 
	 */
	public HeuristicSearch(State startState) {
			
		//Sort the queue according to the state's heuristic weight (distance + heuristic)
		setOpenList(new PriorityQueue<State>(1, 
				new Comparator<State>()
				{
					@Override
					public int compare(State state1, State state2) {
						return (Double.compare(state1.heuristicWeight(), state2.heuristicWeight()));
					}
				})); 
		addState(startState);
		doSearch();
		
	}
	
	public void doSearch(){
		//if(openListQ.size() == 0) return;
		State current = openListQ.element();
		if(current.isAtGoalState()) return;
		
		addChildren(current);
		removeState(current);
		doSearch();
	}

	private void addChildren(State current) {
		for(State state : current.getPossibleMoves()){
			addState(state);
		}
	}
	public void addState(State state)
	{
		//Add only the states that are not already in the priority queue
		if(!openListQ.contains(state) && !closedList.contains(state))
			openListQ.add(state);
	}
	
	public void removeState(State state){
		openListQ.remove(state);
		closedList.add(state);
		//System.out.println(closedList.size());
	}

	
	public String print()
	{
		//System.out.println(openListQ.element().printSequence(""));
		return openListQ.element().printSequence("");
	}
	
	public LinkedList<State> closedList()
	{
		return closedList;
	}
	
	public String printClosedList()
	{
		//System.out.println("\nClosedList");
		String toReturn = "";
		for (State state : closedList) {
			//System.out.println(state);
			toReturn += state;
		}
		
		return toReturn;
	}
	/*
	********************************* GETTERS & SETTERS ************************************
	*/
	
	public PriorityQueue<State> getOpenList() {
		return openListQ;
	}


	public void setOpenList(PriorityQueue<State> openListQ) {
		this.openListQ = openListQ;
	}
	
	
	
	/*
	********************************* GETTERS & SETTERS ************************************
	*/

}
